package com.xbts.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huaweicloud.sdk.bss.v2.BssClient;
import com.huaweicloud.sdk.bss.v2.model.*;
import com.huaweicloud.sdk.bss.v2.region.BssRegion;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.ecs.v2.EcsClient;
import com.huaweicloud.sdk.ecs.v2.model.*;
import com.huaweicloud.sdk.ecs.v2.region.EcsRegion;
import com.huaweicloud.sdk.eip.v2.EipClient;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsRequest;
import com.huaweicloud.sdk.eip.v2.model.ListPublicipsResponse;
import com.huaweicloud.sdk.eip.v2.model.PublicipShowResp;
import com.huaweicloud.sdk.eip.v2.region.EipRegion;
import com.huaweicloud.sdk.iam.v3.IamClient;
import com.huaweicloud.sdk.iam.v3.model.*;
import com.huaweicloud.sdk.iam.v3.region.IamRegion;
import com.huaweicloud.sdk.ims.v2.ImsClient;
import com.huaweicloud.sdk.ims.v2.model.CreateImageResponse;
import com.huaweicloud.sdk.ims.v2.model.ListImagesRequest;
import com.huaweicloud.sdk.ims.v2.model.ListImagesResponse;
import com.huaweicloud.sdk.ims.v2.region.ImsRegion;
import com.huaweicloud.sdk.vpc.v2.VpcClient;
import com.huaweicloud.sdk.vpc.v2.model.*;
import com.huaweicloud.sdk.vpc.v2.region.VpcRegion;
import com.xbts.common.constant.Constants;
import com.xbts.common.core.domain.AjaxResult;
import com.xbts.common.core.domain.entity.SysUser;
import com.xbts.common.core.domain.model.LoginUser;
import com.xbts.common.core.redis.RedisCache;
import com.xbts.common.enums.HttpMethod;
import com.xbts.common.enums.ServerStatusEnum;
import com.xbts.common.enums.SettingEnum;
import com.xbts.common.enums.ShoppingCarEnums;
import com.xbts.common.exception.ServiceException;
import com.xbts.common.utils.DateUtils;
import com.xbts.common.utils.list.ListUtils;
import com.xbts.common.utils.SecurityUtils;
import com.xbts.common.utils.SnowFlakeUtil;
import com.xbts.common.utils.StringUtils;
import com.xbts.common.utils.bean.BeanUtils;
import com.xbts.system.domain.*;
import com.xbts.system.domain.dto.*;
import com.xbts.system.enums.OrderStatusEnum;
import com.xbts.system.enums.OrderTypeEnum;
import com.xbts.system.mapper.SysUserMapper;
import com.xbts.system.module.payment.enums.PaymentMethodEnum;
import com.xbts.system.module.payment.service.ICnWalletLogService;
import com.xbts.system.module.sms.HttpUtils;
import com.xbts.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CloudServiceServiceImpl implements ICloudServiceService {

    private final static String MESSAGE = "该规格已售罄或者已下架，建议您选购其他规格。";

    @Autowired
    private SettingService settingService;
    @Autowired
    private ICnRegionService cnRegionService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ICnShoppingCarService cnShoppingCarService;
    @Autowired
    private ICnOrderService cnOrderService;
    @Autowired
    private ICnOrderItemService cnOrderItemService;
    @Autowired
    private ICnWalletLogService cnWalletLogService;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private ICnUserCloudServersRelationService userCloudServersRelationService;
    @Autowired
    private ICnWeChatTemplateMsgService cnWeChatTemplateMsgService;

    @Override
    public NovaListAvailabilityZonesResponse novaListAvailabilityZones(String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
        NovaListAvailabilityZonesRequest request = new NovaListAvailabilityZonesRequest();
        NovaListAvailabilityZonesResponse response = null;
        try {
            response = client.novaListAvailabilityZones(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("查询可用区列表失败", e);
        }
        if (response != null && response.getAvailabilityZoneInfo() != null) {
            List<NovaAvailabilityZone> collect = response.getAvailabilityZoneInfo()
                    .stream().filter(availabilityZoneInfo -> availabilityZoneInfo.getZoneState().getAvailable()).collect(Collectors.toList());
            response.setAvailabilityZoneInfo(collect);
            return response;
        } else {
            return null;
        }
    }

    @Override
    public List<Flavor> listFlavors(ListFlavorsRequestDTO listFlavorsRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = listFlavorsRequestDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
//        CnRegion cnRegion = cnRegionService.selectCnRegionByRegionId(regionId);
//        String projectId = cnRegion.getProjectId();
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();

        ListFlavorsResponse response = null;
        try {
            response = client.listFlavors(listFlavorsRequestDTO);
            // 获取规格价格
        } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) {
            log.error("查询云服务器规格列表失败", e);
        }

        if (null == response || response.getFlavors().isEmpty()) return new ArrayList<>();
//        ICredential iCredential = new GlobalCredentials()
//                .withAk(accountSetting.getAccessKeyId())
//                .withSk(accountSetting.getSecretAccessKey());
//        BssClient bssClient = BssClient.newBuilder()
//                .withCredential(iCredential)
//                .withRegion(BssRegion.valueOf("cn-north-1"))
//                .build();
//        ListRateOnPeriodDetailRequest listRateOnPeriodDetailRequest = new L   istRateOnPeriodDetailRequest();
//        RateOnPeriodReq body = new RateOnPeriodReq();
//        ListFlavorsResponseDTO listFlavorsResponseDTO = new ListFlavorsResponseDTO();
//        BeanUtils.copyBeanProp(listFlavorsResponseDTO, response);
//        listFlavorsResponseDTO.setRegionId(regionId);
//
//        log.info("listFlavorsResponseDTO: " + listFlavorsResponseDTO.getFlavors().size());
//        List<PeriodProductInfo> listbodyProductInfos = getFlavorsParams(listFlavorsResponseDTO);
//
//        Map<Integer, Double> map = new HashMap<>();
//        List<List<PeriodProductInfo>> lists = ListUtils.divideArrays(listbodyProductInfos, 100);
//
//        for (int i = 0; i < lists.size(); i++) {
//            List<PeriodProductInfo> periodProductInfos = lists.get(i);
//            body.withProductInfos(periodProductInfos);
//            body.withProjectId(projectId);
//            listRateOnPeriodDetailRequest.withBody(body);
//            log.info("listRateOnPeriodDetailRequest = " + JSONObject.toJSONString(listRateOnPeriodDetailRequest));
//            ListRateOnPeriodDetailResponse periodDetailResponse = bssClient.listRateOnPeriodDetail(listRateOnPeriodDetailRequest);
//            List<PeriodProductOfficialRatingResult> productRatingResults = periodDetailResponse.getOfficialWebsiteRatingResult().getProductRatingResults();
//            for (PeriodProductOfficialRatingResult productRatingResult : productRatingResults) {
//                map.put(Integer.parseInt(productRatingResult.getId()), productRatingResult.getOfficialWebsiteAmount());
//            }
//        }
//        List<FlavorVO> flavors = new ArrayList<>(response.getFlavors().size());
//        for (int i = 1; i <= response.getFlavors().size(); i++) {
//            Flavor flavor = response.getFlavors().get(i - 1);
//            FlavorVO flavorVo = new FlavorVO();
//            BeanUtils.copyBeanProp(flavorVo, flavor);
//            flavors.add(flavorVo);
//        }
//        // 过滤价格为null的数据
//        flavors = flavors.stream().filter(flavorVO -> flavorVO.getPrice() != null).collect(Collectors.toList());
        return response.getFlavors();
    }

    @Override
    public Map<String, Object> listRateOnPeriodDetail(RateOnPeriodReqDTO rateOnPeriodReq) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = rateOnPeriodReq.getRegionId();
        if (StringUtils.isEmpty(regionId)) {
            regionId = accountSetting.getRegionId();
            rateOnPeriodReq.setRegionId(regionId);
        }
        CnRegion cnRegion = cnRegionService.selectCnRegionByRegionId(regionId);
        rateOnPeriodReq.setEipType(cnRegion.getEipType());
        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        ListRateOnPeriodDetailRequest request = new ListRateOnPeriodDetailRequest();
        rateOnPeriodReq.withProjectId(cnRegion.getProjectId());

        // 构建请求参数
        genListOnDemandResourceRatingsRequest(rateOnPeriodReq);
        request.withBody(rateOnPeriodReq);
        ListRateOnPeriodDetailResponse response = null;
        try {
            response = client.listRateOnPeriodDetail(request);
        } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) {
            log.error("查询云服务器规格价格失败", e);
            throw new ServiceException(MESSAGE);
        }
        if (response == null){
            throw new ServiceException(MESSAGE);
        }
        Double amount = getAmount(response);
        BigDecimal price = new BigDecimal(amount).setScale(2, RoundingMode.HALF_UP);
        Map<String, Object> map = new HashMap<>();
        String priceKey = "priceKey_" + SnowFlakeUtil.getSnowFlakeId();
        map.put("priceKey", priceKey);
        map.put("price", price);

        Map<String, Object> cacheMap = new HashMap<>();
        cacheMap.put("response", response);
        cacheMap.put("priceKey", priceKey);
        cacheMap.put("price", price);
        cacheMap.put("priceQueryJsonStr", JSON.toJSONString(rateOnPeriodReq.getProductInfos()));
        redisCache.setCacheObject(priceKey, cacheMap, 30, TimeUnit.MINUTES);
        return map;
    }

//    @Override
    public Map<String, Object> resizeFlavorPrice2(RateOnPeriodReqDTO rateOnPeriodReq) {

        String jsonStr = rateOnPeriodReq.getJsonStr();
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String id = jsonObject.getString("id");
        Integer type = jsonObject.getInteger("type");

        // 返回Map
        Map<String, Object> map = new HashMap<>();
        BigDecimal price = BigDecimal.ZERO;

        // 获取服务器的到期时间
        CnUserCloudServersRelation serversRelation = userCloudServersRelationService.getById(id);

        Date expirationTime = serversRelation.getExpirationTime();
        // 查询当前时间到过期时间还剩多少天
        int days = DateUtils.differentDaysByMillisecond(new Date(), expirationTime);
        if(days <= 0){
            throw new ServiceException("服务器已过期，不可变更！");
        }

        String orderItemId = serversRelation.getOrderItemId();
        CnOrderItem orderItem = cnOrderItemService.getById(orderItemId);
        JSONObject parseObject = JSONObject.parseObject(orderItem.getJsonStr());
        JSONObject extendparam = parseObject.getJSONObject("extendparam");
        String periodTypeStr = extendparam.getString("periodType");
        Integer periodNum = extendparam.getInteger("periodNum");

        // 购买方式
        Integer periodType = 3;
        // 剩余时间占比
        BigDecimal remainTimeProportion;


        // 获取该服务器所有订单
        List<CnOrderItem> orderItemList = cnOrderItemService.list(new LambdaQueryWrapper<CnOrderItem>()
                .eq(CnOrderItem::getRegionId, serversRelation.getRegionId())
                .eq(CnOrderItem::getShoppingCarEnums, ShoppingCarEnums.CLOUD_SERVER_RENEW)
                .ge(CnOrderItem::getEndTime, new Date()));
        orderItemList.add(orderItem);

        // 未使用的订单的月份总量
        Integer notUsed = 0;
        // 未使用的类型
        Integer notUsedType = 2;
        // 未使用的各类型价格
        // 规格
        BigDecimal notUsedEc2Price = BigDecimal.ZERO;
        // 磁盘
        BigDecimal notUsedEbsPrice = BigDecimal.ZERO;
        // 带宽
        BigDecimal notUsedVpcPrice = BigDecimal.ZERO;
        // 如果按包年计算可能会超量计算，比如未使用20个月，按包2年计算，则会超出20个月，所以需要计算剩余时间占比   占比为 20/(12 * 2)
        BigDecimal notUsedResidueProportion = BigDecimal.ONE;

        // 正在使用的月份总量
        Integer inUse = 0;
        // 剩余的月份数量
        Integer residue = 1;
        // 正在使用的类型
        Integer inUseType = 2;
        // 已使用的各类型价格
        // 规格
        BigDecimal inUseEc2Price = BigDecimal.ZERO;
        // 磁盘
        BigDecimal inUseEbsPrice = BigDecimal.ZERO;
        // 带宽
        BigDecimal inUseVpcPrice = BigDecimal.ZERO;
        // 已使用剩余占比
        BigDecimal inUseResidueProportion = BigDecimal.ONE;

        // 遍历订单列表
        for (CnOrderItem cnOrderItem : orderItemList) {
            Date beginTime = cnOrderItem.getBeginTime();
            Date endTime = cnOrderItem.getEndTime();
            Date now = new Date();
            Integer periodType1 = cnOrderItem.getPeriodType();
            Integer PeriodNum = cnOrderItem.getPeriodNum();
            if(DateUtils.differentDaysByMillisecond(now, beginTime) > 0){
                notUsed += PeriodNum * (periodType1 == 30 ? 1 : 12);
                notUsedEc2Price = notUsedEc2Price.add(cnOrderItem.getEc2Price());
                notUsedEbsPrice = notUsedEbsPrice.add(cnOrderItem.getEbsPrice());
                notUsedVpcPrice = notUsedVpcPrice.add(cnOrderItem.getVpcPrice());
            } else {
                inUse += PeriodNum * (periodType1 == 30 ? 1 : 12);
                inUseType = periodType1 == 30 ? 2 : 3;
                residue = (DateUtils.differentDaysByMillisecond(now, endTime) + 29) / 30;
                inUseResidueProportion = new BigDecimal((double)residue / inUse).setScale(2, BigDecimal.ROUND_HALF_UP);
                inUseEc2Price = inUseEc2Price.add(cnOrderItem.getEc2Price());
                inUseEbsPrice = inUseEbsPrice.add(cnOrderItem.getEbsPrice());
                inUseVpcPrice = inUseVpcPrice.add(cnOrderItem.getVpcPrice());
            }
        }


        if(type == 1) {
            String flavorRef = jsonObject.getString("flavorRef");

            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId("1");
            periodProductInfo.setRegion("cn-east-3");
            periodProductInfo.setAvailableZone("cn-east-3");
            periodProductInfo.setSubscriptionNum(1);

            periodProductInfo.setCloudServiceType("hws.service.type.ec2");
            periodProductInfo.setResourceType("hws.resource.type.vm");
            periodProductInfo.setResourceSpec(flavorRef + ".linux");

            // 获取正在使用的部分变更后的差价
            // 1,获取正在使用的计费模式的总价
            periodProductInfo.setPeriodType(inUseType);
            periodProductInfo.setPeriodNum(inUse);

            productInfos.add(periodProductInfo);
            // 计算价格
            rateOnPeriodReq.setProductInfos(productInfos);
            // 查询价格
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);
            BigDecimal inUseAmount = new BigDecimal(amount);

            // 2,根据此段时间的剩余时间占比，获取原始金额占比
            BigDecimal inUseAmountOld = inUseEc2Price.multiply(inUseResidueProportion);
            // 3,根据此段时间的剩余时间占比，获取新规格金额占比
            BigDecimal inUseAmountNow = inUseAmount.multiply(inUseResidueProportion);
            // 4,获得新规格需补差价
            BigDecimal inUserAupplementAmount = inUseAmountNow.subtract(inUseAmountOld);
            if(inUserAupplementAmount.compareTo(BigDecimal.ZERO) < 0){
                inUserAupplementAmount = BigDecimal.ZERO;
            }
            BigDecimal notUsedAupplementAmount = BigDecimal.ZERO;
            if(notUsed > 0) {
                // 获取未使用的部分变更后的差价
                // 1,获取未使用的计费模式的总价
                if(notUsed > 11){
                    notUsedType = 3;
                    residue = (notUsed + 11) / 12;

                    periodProductInfo.setPeriodType(notUsedType);
                    periodProductInfo.setPeriodNum(residue);
                } else {
                    periodProductInfo.setPeriodType(notUsedType);
                    periodProductInfo.setPeriodNum(notUsed);
                }

                // 查询价格
                Map<String, Object> notUsedStringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
                String notUsedPriceKey = (String)notUsedStringObjectMap.get("priceKey");
                Map<String, Object> notUsedCacheMap = (Map<String, Object>)redisCache.getCacheObject(notUsedPriceKey);
                ListRateOnPeriodDetailResponse notUsedResponseNew = (ListRateOnPeriodDetailResponse) notUsedCacheMap.get("response");
                Double notUsedAmount = getAmount(notUsedResponseNew);
                BigDecimal notUsedAmountOld = BigDecimal.ZERO;
                // 2,根据此段时间的剩余时间占比，获取原始金额占比
                if(notUsed > 11){
                    notUsedResidueProportion = new BigDecimal((double)notUsed / residue * 12).setScale(2, BigDecimal.ROUND_HALF_UP);
                    notUsedAmountOld = notUsedEc2Price.multiply(notUsedResidueProportion);
                }
                // 3,根据此段时间的剩余时间占比，获取新规格金额占比
                BigDecimal notUsedAmountNow = new BigDecimal(notUsedAmount).multiply(notUsedResidueProportion);
                // 4,获得新规格需补差价
                notUsedAupplementAmount = notUsedAmountOld.subtract(notUsedAmountNow);
                if(notUsedAupplementAmount.compareTo(BigDecimal.ZERO) < 0){
                    notUsedAupplementAmount = BigDecimal.ZERO;
                }
            }
            // 总差价
            price = inUserAupplementAmount.add(notUsedAupplementAmount);
            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",变更服务器规格为：" + flavorRef);
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else if(type == 2) {
            JSONArray disks = jsonObject.getJSONArray("disks");
            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            if(disks == null || disks.size() == 0){
                map.put("price", 0D);
                return map;
            }
            String orderAbstract = "";
            for (int i = 0; i < disks.size(); i++) {
                // 获取新增磁盘数组
                JSONObject disk = disks.getJSONObject(i);

                // 封装磁盘查询价格参数
                PeriodProductInfo diskPeriodProductInfo = new PeriodProductInfo();
                int diskPeriodProductInfoId = i + 1;
                diskPeriodProductInfo.setId(diskPeriodProductInfoId + "");
                diskPeriodProductInfo.setCloudServiceType("hws.service.type.ebs");
                diskPeriodProductInfo.setResourceType("hws.resource.type.volume");
                diskPeriodProductInfo.setRegion("cn-east-3");
                diskPeriodProductInfo.setAvailableZone("cn-east-3");
                diskPeriodProductInfo.setPeriodType(inUseType);
                diskPeriodProductInfo.setPeriodNum(inUse);
                diskPeriodProductInfo.setSubscriptionNum(1);
                diskPeriodProductInfo.setResourceSpec(disk.getString("diskType"));
                diskPeriodProductInfo.setResourceSize(disk.getInteger("size"));
                diskPeriodProductInfo.setSizeMeasureId(17);
                productInfos.add(diskPeriodProductInfo);

                orderAbstract += "[" + disk.getString("diskType") + "-" + disk.getInteger("size") + "GB];";
            }
            // 查询价格
            rateOnPeriodReq.setProductInfos(productInfos);
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);

            BigDecimal inUseAmount = new BigDecimal(amount).multiply(inUseResidueProportion);
            BigDecimal notUsedAupplementAmount = BigDecimal.ZERO;
            if(notUsed > 0) {
                // 获取未使用的部分变更后的差价
                for (PeriodProductInfo diskPeriodProductInfo : productInfos) {
                    if (notUsed > 11) {
                        notUsedType = 3;
                        residue = (notUsed + 11) / 12;
                        diskPeriodProductInfo.setPeriodType(notUsedType);
                        diskPeriodProductInfo.setPeriodNum(residue);
                    } else {
                        diskPeriodProductInfo.setPeriodType(notUsedType);
                        diskPeriodProductInfo.setPeriodNum(notUsed);
                    }
                }
                // 查询价格
                Map<String, Object> notUsedStringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
                String notUsedPriceKey = (String)notUsedStringObjectMap.get("priceKey");
                Map<String, Object> notUsedCacheMap = (Map<String, Object>)redisCache.getCacheObject(notUsedPriceKey);
                ListRateOnPeriodDetailResponse notUsedResponseNew = (ListRateOnPeriodDetailResponse) notUsedCacheMap.get("response");
                Double notUsedAmount = getAmount(notUsedResponseNew);
                BigDecimal notUsedAmountOld = BigDecimal.ZERO;
                // 2,根据此段时间的剩余时间占比，获取原始金额占比
                if(notUsed > 11){
                    notUsedResidueProportion = new BigDecimal((double)notUsed / residue * 12).setScale(2, BigDecimal.ROUND_HALF_UP);
                    notUsedAmountOld = notUsedEc2Price.multiply(notUsedResidueProportion);
                }
                // 3,根据此段时间的剩余时间占比，获取新规格金额占比
                BigDecimal notUsedAmountNow = new BigDecimal(notUsedAmount).multiply(notUsedResidueProportion);
                // 4,获得新规格需补差价
                notUsedAupplementAmount = notUsedAmountOld.subtract(notUsedAmountNow);
                if(notUsedAupplementAmount.compareTo(BigDecimal.ZERO) < 0){
                    notUsedAupplementAmount = BigDecimal.ZERO;
                }

            }

            price = inUseAmount.add(notUsedAupplementAmount);

            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",新增磁盘：" + orderAbstract);
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else if(type == 3) {
            // 带宽类型
            String bandwidthType = jsonObject.getString("bandwidthType");
            // 带宽大小
            Integer bandwidthSize = jsonObject.getInteger("bandwidthSize");

            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId("1");
            periodProductInfo.setRegion("cn-east-3");
            periodProductInfo.setAvailableZone("cn-east-3a");
            periodProductInfo.setPeriodType(inUseType);
            periodProductInfo.setPeriodNum(inUse);
            periodProductInfo.setSubscriptionNum(1);

            periodProductInfo.setCloudServiceType("hws.service.type.vpc");
            periodProductInfo.setResourceType("hws.resource.type.bandwidth");
            periodProductInfo.setResourceSpec(bandwidthType);
            periodProductInfo.setResourceSize(bandwidthSize);
            productInfos.add(periodProductInfo);


            // 查询价格
            rateOnPeriodReq.setProductInfos(productInfos);
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);
            BigDecimal inUseAmount = new BigDecimal(amount);
            // 获取规格原始价格
            // 2,根据此段时间的剩余时间占比，获取原始金额占比
            BigDecimal inUseAmountOld = inUseVpcPrice.multiply(inUseResidueProportion);
            // 3,根据此段时间的剩余时间占比，获取新规格金额占比
            BigDecimal inUseAmountNow = inUseAmount.multiply(inUseResidueProportion);
            // 4,获得新规格需补差价
            BigDecimal inUserAupplementAmount = inUseAmountNow.subtract(inUseAmountOld);

            // 计算未使用部分的差价
            BigDecimal notUsedAupplementAmount = BigDecimal.ZERO;
            if(notUsed > 0) {
                // 获取未使用的部分变更后的差价
                if (notUsed > 11) {
                    notUsedType = 3;
                    residue = (notUsed + 11) / 12;
                    periodProductInfo.setPeriodType(notUsedType);
                    periodProductInfo.setPeriodNum(residue);
                } else {
                    periodProductInfo.setPeriodType(notUsedType);
                    periodProductInfo.setPeriodNum(notUsed);
                }
                // 查询价格
                Map<String, Object> notUsedStringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
                String notUsedPriceKey = (String)notUsedStringObjectMap.get("priceKey");
                Map<String, Object> notUsedCacheMap = (Map<String, Object>)redisCache.getCacheObject(notUsedPriceKey);
                ListRateOnPeriodDetailResponse notUsedResponseNew = (ListRateOnPeriodDetailResponse) notUsedCacheMap.get("response");
                Double notUsedAmount = getAmount(notUsedResponseNew);
                BigDecimal notUsedAmountOld = BigDecimal.ZERO;
                // 2,根据此段时间的剩余时间占比，获取原始金额占比
                if(notUsed > 11){
                    notUsedResidueProportion = new BigDecimal((double)notUsed / residue * 12).setScale(2, BigDecimal.ROUND_HALF_UP);
                    notUsedAmountOld = notUsedEc2Price.multiply(notUsedResidueProportion);
                }
                // 3,根据此段时间的剩余时间占比，获取新规格金额占比
                BigDecimal notUsedAmountNow = new BigDecimal(notUsedAmount).multiply(notUsedResidueProportion);
                // 4,获得新规格需补差价
                notUsedAupplementAmount = notUsedAmountOld.subtract(notUsedAmountNow);
                if(notUsedAupplementAmount.compareTo(BigDecimal.ZERO) < 0){
                    notUsedAupplementAmount = BigDecimal.ZERO;
                }
            }
            price = inUserAupplementAmount.add(notUsedAupplementAmount);
            if(price.compareTo(BigDecimal.ZERO) < 0){
                price = BigDecimal.ZERO;
            }
            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",变更带宽为：" + (bandwidthType.equals("19_bgp") ? "动态" + bandwidthSize + "Mbps" : "静态" + bandwidthSize + "Mbps"));
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else {
            throw new ServiceException("变更类型异常!");
        }
        String priceKey = "priceKey_" + SnowFlakeUtil.getSnowFlakeId();

        price = price.setScale(2, BigDecimal.ROUND_HALF_UP);
        map.put("priceKey", priceKey);
        map.put("price", price);
        map.put("relationId", serversRelation.getRelationId());


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("priceKey", priceKey);
        resultMap.put("price", price);
        redisCache.setCacheObject(priceKey, map, 30, TimeUnit.MINUTES);
        return resultMap;
    }

    public Map<String, Object> resizeFlavorPrice(RateOnPeriodReqDTO rateOnPeriodReq) {

        String jsonStr = rateOnPeriodReq.getJsonStr();
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String id = jsonObject.getString("id");
        Integer type = jsonObject.getInteger("type");

        // 返回Map
        Map<String, Object> map = new HashMap<>();
        BigDecimal price = BigDecimal.ZERO;

        // 获取服务器的到期时间
        CnUserCloudServersRelation serversRelation = userCloudServersRelationService.getById(id);

        Date expirationTime = serversRelation.getExpirationTime();
        // 查询当前时间到过期时间还剩多少天
        int days = DateUtils.differentDaysByMillisecond(new Date(), expirationTime);
        if(days <= 0){
            throw new ServiceException("服务器已过期，不可变更！");
        }

        // 总月份
        Integer months = serversRelation.getMonths();
        // 规格总消费
        BigDecimal ec2Price = serversRelation.getEc2Price();
        // 磁盘总消费
        BigDecimal ebsPrice = serversRelation.getEbsPrice();
        // 带宽总消费
        BigDecimal vpcPrice = serversRelation.getVpcPrice();

        // 获取 剩余时长/总时长
        BigDecimal remainingTimeProportion = new BigDecimal(days).divide(new BigDecimal("30.4").multiply(new BigDecimal(months)), 4, BigDecimal.ROUND_HALF_UP);
        // 原始规格剩余时长的剩余价值
        BigDecimal ec2ResidualValue = ec2Price.multiply(remainingTimeProportion);
        // 原始磁盘剩余时长的剩余价值
//        BigDecimal ebsResidualValue = ebsPrice.multiply(remainingTimeProportion);
        // 原始带宽剩余时长的剩余价值
        BigDecimal vpcResidualValue = vpcPrice.multiply(remainingTimeProportion);


        // 计算需要查询的方式和数量
        // 计费方式
        Integer periodType = 2;
        // 计费数量
        Integer periodNum = 1;
        // 计算价格后需乘的比例  days / 计算的时长
        BigDecimal residue = BigDecimal.ZERO;
        if(days > 365){
            periodType = 3;
            // 向上取整
            periodNum = (days + 364) / 365;
            residue = new BigDecimal((double)days / (periodNum * 365)).setScale(4, BigDecimal.ROUND_HALF_UP);
        } else {
            periodType = 2;
            // 向上取整
            periodNum = (days + 29) / 30;
            residue = new BigDecimal((double)days / ((double)periodNum * 30.4)).setScale(4, BigDecimal.ROUND_HALF_UP);
        }

        if(type == 1) {
            String flavorRef = jsonObject.getString("flavorRef");

            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId("1");
            periodProductInfo.setRegion("cn-east-3");
            periodProductInfo.setAvailableZone("cn-east-3");
            periodProductInfo.setSubscriptionNum(1);

            periodProductInfo.setCloudServiceType("hws.service.type.ec2");
            periodProductInfo.setResourceType("hws.resource.type.vm");
            periodProductInfo.setResourceSpec(flavorRef + ".linux");

            // 获取正在使用的部分变更后的差价
            // 1,获取正在使用的计费模式的总价
            periodProductInfo.setPeriodType(periodType);
            periodProductInfo.setPeriodNum(periodNum);

            productInfos.add(periodProductInfo);
            // 计算价格
            rateOnPeriodReq.setProductInfos(productInfos);
            // 查询价格
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);
            // 剩余时长 所选规格需要的价格
            BigDecimal newAmount = new BigDecimal(amount).multiply(residue);
            // 差价
            price = newAmount.subtract(ec2ResidualValue);
            if(price.compareTo(BigDecimal.ZERO) <= 0){
                price = BigDecimal.ZERO;
            }
            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",变更服务器规格为：" + flavorRef);
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else if(type == 2) {
            JSONArray disks = jsonObject.getJSONArray("disks");
            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            if(disks == null || disks.size() == 0){
                map.put("price", 0D);
                return map;
            }
            String orderAbstract = "";
            for (int i = 0; i < disks.size(); i++) {
                // 获取新增磁盘数组
                JSONObject disk = disks.getJSONObject(i);

                // 封装磁盘查询价格参数
                PeriodProductInfo diskPeriodProductInfo = new PeriodProductInfo();
                int diskPeriodProductInfoId = i + 1;
                diskPeriodProductInfo.setId(diskPeriodProductInfoId + "");
                diskPeriodProductInfo.setCloudServiceType("hws.service.type.ebs");
                diskPeriodProductInfo.setResourceType("hws.resource.type.volume");
                diskPeriodProductInfo.setRegion("cn-east-3");
                diskPeriodProductInfo.setAvailableZone("cn-east-3");
                diskPeriodProductInfo.setPeriodType(periodType);
                diskPeriodProductInfo.setPeriodNum(periodNum);
                diskPeriodProductInfo.setSubscriptionNum(1);
                diskPeriodProductInfo.setResourceSpec(disk.getString("diskType"));
                diskPeriodProductInfo.setResourceSize(disk.getInteger("size"));
                diskPeriodProductInfo.setSizeMeasureId(17);
                productInfos.add(diskPeriodProductInfo);

                orderAbstract += "[" + disk.getString("diskType") + "-" + disk.getInteger("size") + "GB];";
            }
            // 查询价格
            rateOnPeriodReq.setProductInfos(productInfos);
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);
            // 剩余时长 所选磁盘需要的价格
            BigDecimal newAmount = new BigDecimal(amount).multiply(residue);
            // 差价
//            price = newAmount.subtract(ebsResidualValue);
            price = newAmount;
            if(price.compareTo(BigDecimal.ZERO) <= 0){
                price = BigDecimal.ZERO;
            }

            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",新增磁盘：" + orderAbstract);
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else if(type == 3) {
            // 带宽类型
            String bandwidthType = jsonObject.getString("bandwidthType");
            // 带宽大小
            Integer bandwidthSize = jsonObject.getInteger("bandwidthSize");

            // 封装查询价格参数
            List<PeriodProductInfo> productInfos = new ArrayList<>();
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId("1");
            periodProductInfo.setRegion("cn-east-3");
            periodProductInfo.setAvailableZone("cn-east-3a");
            periodProductInfo.setPeriodType(periodType);
            periodProductInfo.setPeriodNum(periodNum);
            periodProductInfo.setSubscriptionNum(1);

            periodProductInfo.setCloudServiceType("hws.service.type.vpc");
            periodProductInfo.setResourceType("hws.resource.type.bandwidth");
            periodProductInfo.setResourceSpec(bandwidthType);
            periodProductInfo.setResourceSize(bandwidthSize);
            productInfos.add(periodProductInfo);

            // 查询价格
            rateOnPeriodReq.setProductInfos(productInfos);
            Map<String, Object> stringObjectMap = listRateOnPeriodDetail(rateOnPeriodReq);
            String priceKey = (String)stringObjectMap.get("priceKey");
            Map<String, Object> cacheMap = (Map<String, Object>)redisCache.getCacheObject(priceKey);
            ListRateOnPeriodDetailResponse responseNew = (ListRateOnPeriodDetailResponse) cacheMap.get("response");
            Double amount = getAmount(responseNew);
            // 剩余时长 所选磁盘需要的价格
            BigDecimal newAmount = new BigDecimal(amount).multiply(residue);
            // 差价
            price = newAmount.subtract(vpcResidualValue);
            if(price.compareTo(BigDecimal.ZERO) <= 0){
                price = BigDecimal.ZERO;
            }
            map.put("orderAbstract", "服务器" + serversRelation.getRelationId() + ",变更带宽为：" + (bandwidthType.equals("19_bgp") ? "动态" + bandwidthSize + "Mbps" : "静态" + bandwidthSize + "Mbps"));
            map.put("priceQueryJsonStr", cacheMap.get("priceQueryJsonStr"));
        } else {
            throw new ServiceException("变更类型异常!");
        }
        String priceKey = "priceKey_" + SnowFlakeUtil.getSnowFlakeId();

        price = price.setScale(2, BigDecimal.ROUND_HALF_UP);
        map.put("priceKey", priceKey);
        map.put("price", price);
        map.put("relationId", serversRelation.getRelationId());
        map.put("type", type);


        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("priceKey", priceKey);
        resultMap.put("price", price);
        redisCache.setCacheObject(priceKey, map, 30, TimeUnit.MINUTES);
        return resultMap;
    }

    @Override
    public CreateSubnetResponse createSubnet(RegionIdDTO<CreateSubnetRequest> regionIdDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = regionIdDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        VpcClient client = VpcClient.newBuilder()
                .withCredential(auth)
                .withRegion(VpcRegion.valueOf(regionId))
                .build();
        CreateSubnetRequest request = regionIdDTO.getBody();
        CreateSubnetResponse response = client.createSubnet(request);

        return response;
    }

    // 获取价格
    private Double getAmount(ListRateOnPeriodDetailResponse response){
        Double amount;
//        List<OptionalDiscountRatingResult> optionalDiscountRatingResults = response.getOptionalDiscountRatingResults();
//        if(StringUtils.isNotNull(optionalDiscountRatingResults) && optionalDiscountRatingResults.size() > 0){
//            amount = optionalDiscountRatingResults.get(0).getAmount();
//        } else {
            OfficialWebsiteRatingResult officialWebsiteRatingResult = response.getOfficialWebsiteRatingResult();
            amount = officialWebsiteRatingResult.getOfficialWebsiteAmount();
//        }
        return amount;
    }


    @Override
    public ListImagesResponse glanceListImages(ListImagesRequestDTO listImagesRequest) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = listImagesRequest.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        ImsClient client = ImsClient.newBuilder()
                .withCredential(auth)
                .withRegion(ImsRegion.valueOf(regionId))
                .build();
//        listImagesRequest.withImagetype(ListImagesRequest.ImagetypeEnum.fromValue("gold"));
//        listImagesRequest.withStatus(ListImagesRequest.StatusEnum.fromValue("active"));
//        listImagesRequest.setVirtualEnvType(ListImagesRequest.VirtualEnvTypeEnum.FUSIONCOMPUTE); // 镜像使用的环境类型 云服务器镜像（即系统盘镜像），则取值为FusionCompute。
        ListImagesResponse response = null;
        try {
            response = client.listImages(listImagesRequest);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("查询镜像列表失败", e);
        }
        return response;
    }

    @Override
    public CreateImageResponse createImage(CreateImageRequestDTO createImageRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = createImageRequestDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        ImsClient client = ImsClient.newBuilder()
                .withCredential(auth)
                .withRegion(ImsRegion.valueOf(regionId))
                .build();
        CreateImageResponse response = null;
        try {
            response = client.createImage(createImageRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("创建镜像失败", e);
        }
        return response;
    }

    @Override
    public JSONObject networks(String regionId) {
        CnRegion cnRegion = cnRegionService.selectCnRegionByRegionId(regionId);
        String url = String.format("https://%s/v2.1/%s/os-networks", cnRegion.getEndPoint(), cnRegion.getProjectId());
        HttpEntity httpEntity = HttpUtils.sendHuaWeiCloud(url, HttpMethod.GET.name(), null);
        try {
            if (httpEntity != null) {
                String result = EntityUtils.toString(httpEntity, Constants.UTF8);
                return JSONObject.parseObject(result);
            }
        } catch (IOException e) {
            log.error("获取网络列表失败", e);
        }
        return null;
    }

    @Override
    public ListVpcsResponse listVpcs(String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        VpcClient client = VpcClient.newBuilder()
                .withCredential(auth)
                .withRegion(VpcRegion.valueOf(regionId))
                .build();
        ListVpcsRequest request = new ListVpcsRequest();
        ListVpcsResponse response = null;
        try {
            response = client.listVpcs(request);
        } catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) {
            log.error("查询VPC列表失败", e);
        }
        return response;
    }

    @Override
    public AjaxResult createServers(PrePaidServerDTO prePaidServerDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = prePaidServerDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
//        CnRegion cnRegion = cnRegionService.selectCnRegionByRegionId(regionId);

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
        CreateServersRequest request = new CreateServersRequest();
        CreateServersRequestBody body = new CreateServersRequestBody();

        // 系统盘
        PrePaidServerRootVolume rootVolume = prePaidServerDTO.getRootVolume();
        if (rootVolume.getSize() < 40 || rootVolume.getSize() > 1024) {
            return AjaxResult.error("创建云服务器失败,系统盘大小范围为40-1024G");
        }
        // 数据盘
        List<PrePaidServerDataVolume> dataVolumes = prePaidServerDTO.getDataVolumes();
        if(StringUtils.isNotNull(dataVolumes)) {
            for (PrePaidServerDataVolume dataVolume : dataVolumes) {
                if (dataVolume.getSize() < 10 || dataVolume.getSize() > 32768) {
                    return AjaxResult.error("创建云服务器失败,数据盘大小范围为10-32768G");
                }
            }
        }
        // 带宽大小：bandwidth
        PrePaidServerPublicip publicIp = prePaidServerDTO.getPublicip();
        PrePaidServerEip eip = publicIp.getEip();
        PrePaidServerEipBandwidth bandwidth = eip.getBandwidth();
        bandwidth.setSharetype(PrePaidServerEipBandwidth.SharetypeEnum.PER); // 默认值
        eip.setBandwidth(bandwidth);
//        eip.setIptype(cnRegion.getEipType()); // 默认值
//        eip.setIptype("5_bgp"); // 临时值
        publicIp.setEip(eip);
        prePaidServerDTO.setPublicip(publicIp);

        // 查询VPC列表
        ListVpcsResponse listVpcsResponse = listVpcs(regionId);
        if (listVpcsResponse.getVpcs().isEmpty()) {
            return AjaxResult.error("创建云服务器失败,查询VPC列表失败");
        }
        String vpcId = listVpcsResponse.getVpcs().get(0).getId();
        // 查询子网列表
        ListSubnetsRequestDTO listSubnetsRequestDTO = new ListSubnetsRequestDTO(regionId);
        listSubnetsRequestDTO.setVpcId(vpcId);
        prePaidServerDTO.setVpcid(vpcId);
        ListSubnetsResponse listSubnetsResponse = listSubnets(listSubnetsRequestDTO);
        if (listSubnetsResponse.getSubnets().isEmpty()) {
            return AjaxResult.error("创建云服务器失败,查询子网列表失败");
        }
        String subnetsId = listSubnetsResponse.getSubnets().get(0).getId();
        List<PrePaidServerNic> nics = new ArrayList<>();
        nics.add(new PrePaidServerNic().withSubnetId(subnetsId));
        prePaidServerDTO.setNics(nics);

        PrePaidServerExtendParam extendParam = prePaidServerDTO.getExtendparam();
        /*计费模式，取值为： “prePaid”：预付费，即包年包月 “postPaid”：后付费，即按需付费*/
        extendParam.setChargingMode(PrePaidServerExtendParam.ChargingModeEnum.PREPAID);
        /*isAutoPay 下单订购后，是否自动从客户的账户中支付，而不需要客户手动去进行支付。 “true”：是（自动支付） “false”：否（需要客户手动支付）*/
        extendParam.setIsAutoPay(PrePaidServerExtendParam.IsAutoPayEnum.TRUE);
        prePaidServerDTO.setExtendparam(extendParam);

        CreateServersResponse response = null;
        try {
            body.withServer(prePaidServerDTO);
            // TODO 测试格式
//            body.withDryRun(true);
            request.withBody(body);
            log.info("创建云服务器请求参数: {}", JSONObject.toJSONString(request));
            response = client.createServers(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            log.error("创建云服务器失败a: ", e);
            return AjaxResult.error();
        } catch (ServiceResponseException se) {
            log.error("创建云服务器失败b: {} ", se.getErrorMsg());
            if (se.getErrorCode().equals("Ecs.0923") || se.getErrorCode().equals("Ecs.0067")) {
                return AjaxResult.error("创建云服务器失败，检查华为云总帐号是否有足够的配额");
            }
            return AjaxResult.error(se.getErrorMsg());
        }
        return AjaxResult.success(response);
    }

    @Override
    public ListSubnetsResponse listSubnets(ListSubnetsRequestDTO listSubnetsRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = listSubnetsRequestDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        VpcClient client = VpcClient.newBuilder()
                .withCredential(auth)
                .withRegion(VpcRegion.valueOf(regionId))
                .build();
        ListSubnetsResponse response = null;
        try {
            response = client.listSubnets(listSubnetsRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            log.error("查询子网列表失败", e);
        } catch (ServiceResponseException e) {
            log.error("查询子网列表失败1 ", e);
        }
        return response;
    }

    @Override
    public ShowJobResponse showJob(String jobId, String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
        ShowJobRequest request = new ShowJobRequest();
        request.withJobId(jobId);
        ShowJobResponse response = null;
        try {
            response = client.showJob(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("查询任务失败 ", e);
        }
        return response;
    }

    @Override
    public ListOnDemandResourceRatingsResponse listOnDemandResourceRatings(RateOnDemandReqDTO rateOnDemandReq) {
        String regionId = rateOnDemandReq.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        CnRegion cnRegion = cnRegionService.selectCnRegionByRegionId(regionId);
        rateOnDemandReq.setProjectId(cnRegion.getProjectId());
        rateOnDemandReq.setRegionId(cnRegion.getRegionId());

        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        ListOnDemandResourceRatingsResponse response = null;
        ListOnDemandResourceRatingsRequest listOnDemandResourceRatingsRequest = new ListOnDemandResourceRatingsRequest();

        listOnDemandResourceRatingsRequest.setBody(rateOnDemandReq);
        try {
            // 构造参数
            response = client.listOnDemandResourceRatings(listOnDemandResourceRatingsRequest);
        } catch (ConnectionException | ServiceResponseException | RequestTimeoutException e) {
            e.printStackTrace();
        }
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized AjaxResult buyServer(BuyServerDto buyServerDto) {
        List<String> ids = buyServerDto.getIds();
        // 查询购物车
        LambdaQueryWrapper<CnShoppingCar> cnShoppingCarLambdaQueryWrapper = new LambdaQueryWrapper<>();
        cnShoppingCarLambdaQueryWrapper.in(CnShoppingCar::getShoppingCarId, ids);
        List<CnShoppingCar> shoppingCarList = cnShoppingCarService.list(cnShoppingCarLambdaQueryWrapper);

        if (shoppingCarList.isEmpty()) {
            return AjaxResult.error("购物车不存在");
        }
        // 多个订单摘要合并
        // 如果为空，就返回空字符串
        String orderAbstract = shoppingCarList.stream().map(CnShoppingCar::getOrderAbstract).filter(StringUtils::isNotBlank).collect(Collectors.joining(","));
        Long userId = null;
        Date date = new Date();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        userId = loginUser.getUserId();

        if (ids == null || ids.isEmpty()) {
            return AjaxResult.error("购物车id不能为空");
        }
        Long orderId = SnowFlakeUtil.getSnowFlakeId();
        String sn = "SN" + SnowFlakeUtil.getSnowFlakeId();

        // 生成子订单
        List<CnOrderItem> cnOrderItems = genCnOrderItem(ids, userId, date);
        if (cnOrderItems.isEmpty()) {
            return AjaxResult.error("所选服务器不存在");
        }

        BigDecimal totalOriginalPrice = BigDecimal.ZERO; // 总原始价格
        BigDecimal totalDiscountPrice = BigDecimal.ZERO; // 总优惠价格
        BigDecimal totalUpdatePrice = BigDecimal.ZERO; // 总修改后价格

        for (CnOrderItem cnOrderItem : cnOrderItems) {
            totalOriginalPrice = totalOriginalPrice.add(cnOrderItem.getOriginalPrice());
            totalDiscountPrice = totalDiscountPrice.add(cnOrderItem.getDiscountPrice());
            totalUpdatePrice = totalUpdatePrice.add(cnOrderItem.getUpdatePrice());
            cnOrderItem.setOrderId(orderId);
            cnOrderItem.setUserId(userId);
            cnOrderItem.setSn(sn);
        }
        // 获取用户信息
        SysUser sysUser = userMapper.selectUserById(userId);

        // 订单
        CnOrder cnOrder = new CnOrder();
        cnOrder.setOrderId(orderId);
        cnOrder.setUserId(SecurityUtils.getUserId());
        cnOrder.setUserName(sysUser.getNickName());
//        cnOrder.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
        cnOrder.setShoppingCarType(OrderTypeEnum.USER.name());
        cnOrder.setPaymentMethod(buyServerDto.getPaymentMethod());
        cnOrder.setPaymentVoucherAddress(buyServerDto.getPaymentVoucherAddress());

        // 生成订单号
        cnOrder.setSn(sn);
        cnOrder.setPaymentTime(date);
        cnOrder.setOriginalPrice(totalOriginalPrice);
        cnOrder.setDiscountPrice(totalDiscountPrice);
        cnOrder.setUpdatePrice(totalUpdatePrice);
        cnOrder.setOrderAbstract(orderAbstract);
        cnOrder.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
        cnOrderService.save(cnOrder);

        // 保存子订单
        if (!cnOrderItems.isEmpty()) {
            cnOrderItemService.saveBatch(cnOrderItems);
        }

        // 删除购物车
        cnShoppingCarService.removeByIds(ids);

        BigDecimal balance = sysUser.getUserWallet();
        if (buyServerDto.getPaymentMethod().equals(PaymentMethodEnum.WALLET.name()) && (null == balance || balance.compareTo(totalUpdatePrice) < 0)) {
            throw new ServiceException("余额不足，请充值！");
        } else {
            if(buyServerDto.getPaymentMethod().equals(PaymentMethodEnum.WALLET.name())) {
                // 扣减余额
                cnWalletLogService.updateUserBalanceAndLog(sysUser.getUserId(),
                        totalUpdatePrice.negate(), buyServerDto.getPaymentMethod(), null, cnOrderItems.get(0).getShoppingCarEnums(), cnOrder.getSn(), null);
            }

            cnWeChatTemplateMsgService.sendPendingOrderNotificationMsg(cnOrder.getUserId().toString(), cnOrder);
            return AjaxResult.success(cnOrder);
        }
    }

    @Override
    public AjaxResult buyServerByCorporate(List<String> ids, String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return AjaxResult.error("支付凭证信息不能为空");
        }

        // 查询购物车
        LambdaQueryWrapper<CnShoppingCar> cnShoppingCarLambdaQueryWrapper = new LambdaQueryWrapper<>();
        cnShoppingCarLambdaQueryWrapper.in(CnShoppingCar::getShoppingCarId, ids);
        List<CnShoppingCar> shoppingCarList = cnShoppingCarService.list(cnShoppingCarLambdaQueryWrapper);

        if (shoppingCarList.size() == 0) {
            return AjaxResult.error("购物车不存在");
        }
        if (ids == null || ids.size() == 0) {
            return AjaxResult.error("购物车id不能为空");
        }
        // 多个订单摘要合并
        String orderAbstract = shoppingCarList.stream().map(CnShoppingCar::getOrderAbstract).filter(StringUtils::isNotBlank).collect(Collectors.joining(","));
        Long userId = SecurityUtils.getUserId();
        Date date = new Date();

        Long orderId = SnowFlakeUtil.getSnowFlakeId();
        String sn = "SN" + SnowFlakeUtil.getSnowFlakeId();

        // 生成子订单
        List<CnOrderItem> cnOrderItems = genCnOrderItem(ids, userId, date);
        if (cnOrderItems.size() == 0) {
            return AjaxResult.error("所选服务器不存在");
        }

        BigDecimal totalOriginalPrice = BigDecimal.ZERO; // 总原始价格
        BigDecimal totalDiscountPrice = BigDecimal.ZERO; // 总优惠价格
        BigDecimal totalUpdatePrice = BigDecimal.ZERO; // 总修改后价格

        for (CnOrderItem cnOrderItem : cnOrderItems) {
            totalOriginalPrice = totalOriginalPrice.add(cnOrderItem.getOriginalPrice());
            totalDiscountPrice = totalDiscountPrice.add(cnOrderItem.getDiscountPrice());
            totalUpdatePrice = totalUpdatePrice.add(cnOrderItem.getUpdatePrice());
            cnOrderItem.setOrderId(orderId);
            cnOrderItem.setUserId(userId);
            cnOrderItem.setSn(sn);
        }
        // 获取用户信息
        SysUser sysUser = userMapper.selectUserById(userId);

        // 订单
        CnOrder cnOrder = new CnOrder();
        cnOrder.setOrderId(orderId);
        cnOrder.setUserId(SecurityUtils.getUserId());
        cnOrder.setUserName(sysUser.getNickName());
        cnOrder.setShoppingCarType(OrderTypeEnum.USER.name());
        cnOrder.setPaymentMethod(PaymentMethodEnum.BANK_TRANSFER.name());
        cnOrder.setPaymentVoucherAddress(filePath);

        // 生成订单号
        cnOrder.setSn(sn);
        cnOrder.setPaymentTime(date);
        cnOrder.setOriginalPrice(totalOriginalPrice);
        cnOrder.setDiscountPrice(totalDiscountPrice);
        cnOrder.setUpdatePrice(totalUpdatePrice);
        cnOrder.setOrderAbstract(orderAbstract);
        cnOrderService.save(cnOrder);

        // 保存子订单
        if (!cnOrderItems.isEmpty()) {
            cnOrderItemService.saveBatch(cnOrderItems);
        }

        // 删除购物车
        cnShoppingCarService.removeByIds(ids);
        return AjaxResult.success();
    }

    @Override
    public KeystoneListProjectsResponse keystoneListProjects() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        IamClient client = IamClient.newBuilder()
                .withCredential(auth)
                .withRegion(IamRegion.valueOf(accountSetting.getRegionId()))
                .build();
        KeystoneListProjectsRequest request = new KeystoneListProjectsRequest();
        KeystoneListProjectsResponse response = null;
        try {
            response = client.keystoneListProjects(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("查询项目失败 ", e);
        }
        return response;
    }

    /**
     * 生成子订单
     *
     * @param ids  服务器ids
     * @param date 时间
     * @return 子订单
     */
    private List<CnOrderItem> genCnOrderItem(List<String> ids, Long userId, Date date) {
        // 创建子订单
        List<CnOrderItem> cnOrderItems = new ArrayList<>();
        LambdaQueryWrapper<CnShoppingCar> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CnShoppingCar::getUserId, userId);
        queryWrapper.in(CnShoppingCar::getShoppingCarId, ids);
        List<CnShoppingCar> cnShoppingCars = cnShoppingCarService.list(queryWrapper);
        if (CollectionUtils.isEmpty(cnShoppingCars)) {
            throw new ServiceException("购物车不存在");
        }
        for (CnShoppingCar cnShoppingCar : cnShoppingCars) {
            CnOrderItem cnOrderItem = cnShoppingCar.getCnOrderItem();
            cnOrderItem.setOrderStatus(OrderStatusEnum.IN_PROGRESS);
            cnOrderItem.setCreateTime(date);
            cnOrderItem.setCreateBy(userId + "");
            cnOrderItem.setUpdateTime(date);
            cnOrderItem.setShoppingCarType(OrderTypeEnum.USER.name());
            cnOrderItem.setPriceQueryJsonStr(cnShoppingCar.getPriceQueryJsonStr());

//            if (cnShoppingCar.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER_CHANGE)) {
//                // 服务器变更
//                cnOrderItem.setOrderAbstract(cnShoppingCar.getOrderAbstract());
//
//            } else if (cnShoppingCar.getShoppingCarEnums().equals(ShoppingCarEnums.CLOUD_SERVER_RENEW)){
//                String jsonStr = cnShoppingCar.getJsonStr();
//                JSONObject jsonObject = JSONObject.parseObject(jsonStr);
//                String id = jsonObject.getString("id");
//                Integer periodNum = jsonObject.getInteger("periodNum");
//                Integer periodType = jsonObject.getInteger("periodType");
//                CnUserCloudServersRelation cloudServersRelation = userCloudServersRelationService.getById(id);
//
//                cnOrderItem.setOrderAbstract(cloudServersRelation.getRelationId() + "服务器续费：" + periodNum + (periodType == 3 ? "年" : "月"));
//            }
//                // 服务器续费

            cnOrderItems.add(cnOrderItem);
        }
        return cnOrderItems;
    }

    public List<PeriodProductInfo> getFlavorsParams(ListFlavorsResponseDTO listFlavorsResponseDTO) {
        if (listFlavorsResponseDTO == null) {
            return null;
        }
        List<PeriodProductInfo> periodProductInfos = new ArrayList<>(listFlavorsResponseDTO.getFlavors().size());
        List<Flavor> flavors = listFlavorsResponseDTO.getFlavors();
        List<String> notPriceList = redisCache.getCacheObject(Constants.REGION_IGNORE_FLAVOR_KEY + listFlavorsResponseDTO.getRegionId());

        for (int i = 0; i < flavors.size(); i++) {
            Flavor flavor = flavors.get(i);
            PeriodProductInfo periodProductInfo = new PeriodProductInfo();
            periodProductInfo.setId(String.valueOf(i + 1));
            periodProductInfo.setCloudServiceType("hws.service.type.ec2");
            periodProductInfo.setResourceType("hws.resource.type.vm");
            periodProductInfo.setResourceSpec(flavor.getName() + ".linux");
            periodProductInfo.setRegion(listFlavorsResponseDTO.getRegionId());
            periodProductInfo.setPeriodType(2);
            periodProductInfo.setPeriodNum(1);
            periodProductInfo.setSubscriptionNum(1);
            periodProductInfos.add(periodProductInfo);
        }
        if (CollectionUtils.isEmpty(notPriceList)) {
            return periodProductInfos;
        }
        // 过滤不支持包年包月的规格
        return periodProductInfos.stream().filter(p -> !notPriceList.contains(p.getResourceSpec())).collect(Collectors.toList());
    }

    @Override
    public String keystoneCreateUserTokenByPassword() {
        if (Objects.nonNull((redisCache.getCacheObject(Constants.X_AUTH_TOKEN)))) {
            return redisCache.getCacheObject(Constants.X_AUTH_TOKEN);
        }
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());
        IamClient client = IamClient.newBuilder()
                .withCredential(auth)
                .withRegion(IamRegion.valueOf("cn-east-3"))
                .build();
        KeystoneCreateUserTokenByPasswordRequest request = new KeystoneCreateUserTokenByPasswordRequest();
        KeystoneCreateUserTokenByPasswordRequestBody body = new KeystoneCreateUserTokenByPasswordRequestBody();
        AuthScopeProject projectScope = new AuthScopeProject();
        projectScope.withName(accountSetting.getRegionId());
        AuthScope scopeAuth = new AuthScope();
        scopeAuth.withProject(projectScope);
        PwdPasswordUserDomain domainUser = new PwdPasswordUserDomain();
        domainUser.withName(accountSetting.getDomainName());
        PwdPasswordUser userPassword = new PwdPasswordUser();
        userPassword.withDomain(domainUser)
                .withName(accountSetting.getDomainName())
                .withPassword(accountSetting.getDomainPassword());
        PwdPassword passwordIdentity = new PwdPassword();
        passwordIdentity.withUser(userPassword);
        List<PwdIdentity.MethodsEnum> listIdentityMethods = new ArrayList<>();
        listIdentityMethods.add(PwdIdentity.MethodsEnum.fromValue("password"));
        PwdIdentity identityAuth = new PwdIdentity();
        identityAuth.withMethods(listIdentityMethods)
                .withPassword(passwordIdentity);
        PwdAuth authbody = new PwdAuth();
        authbody.withIdentity(identityAuth)
                .withScope(scopeAuth);
        body.withAuth(authbody);
        request.withBody(body);
        String token = null;
        try {
            KeystoneCreateUserTokenByPasswordResponse response = client.keystoneCreateUserTokenByPassword(request);
            if (response != null) {
                token = response.getXSubjectToken();
                // redis
                redisCache.setCacheObject(Constants.X_AUTH_TOKEN, token, 60 * 60 * 24, TimeUnit.SECONDS);
            } else {
                return null;
            }
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("keystoneCreateUserTokenByPassword error:{}", e.getMessage());
        }
        return token;
    }

    @Override
    public AjaxResult listResizeFlavors(ListResizeFlavorsRequestDTO listResizeFlavorsRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        String regionId = listResizeFlavorsRequestDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        String instanceUuid = listResizeFlavorsRequestDTO.getInstanceUuid();
        if (StringUtils.isEmpty(instanceUuid)) {
            return AjaxResult.error("实例ID不能为空");
        }
        String sourceFlavorId = listResizeFlavorsRequestDTO.getSourceFlavorId();
        if (StringUtils.isEmpty(sourceFlavorId)) {
            return AjaxResult.error("源规格ID不能为空");
        }
        String sourceFlavorName = listResizeFlavorsRequestDTO.getSourceFlavorName();
        if (StringUtils.isEmpty(sourceFlavorName)) {
            return AjaxResult.error("源规格名称不能为空");
        }

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
        ListResizeFlavorsResponse response = null;
        try {
            response = client.listResizeFlavors(listResizeFlavorsRequestDTO);
        } catch (Exception e) {
            log.error("listResizeFlavors error:{}", e.getMessage());
        }
        if (response == null) {
            return AjaxResult.error("获取可升级规格失败");
        }
        return AjaxResult.success(response);
    }

    @Override
    public AjaxResult resizeServer(ResizeServerRequestDTO resizeServerRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = resizeServerRequestDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
        ResizeServerResponse response = null;
        try {
            response = client.resizeServer(resizeServerRequestDTO);
        } catch (Exception e) {
            log.error("resizeServer error:{}", e.getMessage());
        }
        if (response == null) {
            return AjaxResult.error("变更云服务器规格失败");
        }
        return AjaxResult.success(response);
    }

    @Override
    public Domains keystoneListAuthDomains() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());
        IamClient client = IamClient.newBuilder()
                .withCredential(auth)
                .withRegion(IamRegion.valueOf(accountSetting.getRegionId()))
                .build();

        KeystoneListAuthDomainsRequest request = new KeystoneListAuthDomainsRequest();
        KeystoneListAuthDomainsResponse response = null;
        try {
            response = client.keystoneListAuthDomains(request);
            System.out.println(response.toString());
        } catch (Exception e) {
            log.error("keystoneListAuthDomains error:{}", e.getMessage());
        }
        if (response != null && response.getDomains() != null) {
            return response.getDomains().get(0);
        }
        return null;
    }

    @Override
    public List<PublicipShowResp> listPublicips(RegionIdDTO<ListPublicipsRequest> regionIdDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        String regionId = regionIdDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EipClient client = EipClient.newBuilder()
                .withCredential(auth)
                .withRegion(EipRegion.valueOf(regionId))
                .build();
        ListPublicipsResponse response = null;
        try {
            response = client.listPublicips(regionIdDTO.getBody());
        } catch (Exception e) {
            log.error("ListPublicips error:{}", e.getMessage());
        }
        if (response != null && response.getPublicips() != null) {
            return response.getPublicips();
        }
        return null;
    }

    @Override
    public ListPayPerUseCustomerResourcesResponse listPayPerUseCustomerResources(ListPayPerUseCustomerResourcesRequest listPayPerUseCustomerResourcesRequest) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        ListPayPerUseCustomerResourcesResponse response = null;
        try {
            log.info("listPayPerUseCustomerResourcesRequest:-----------{}",listPayPerUseCustomerResourcesRequest.toString());
            response = client.listPayPerUseCustomerResources(listPayPerUseCustomerResourcesRequest);
            log.info("ListPayPerUseCustomerResourcesResponse:-----------{}",response.toString());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("listPayPerUseCustomerResources error:{}", e.getMessage());
        }
        return response;
    }

    @Override
    public DeleteServersResponse deleteServers(RegionIdDTO<DeleteServersRequest> regionIdDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        String regionId = regionIdDTO.getRegionId();
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;

        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EcsClient client = EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();

        DeleteServersResponse response = null;
        try {
            response = client.deleteServers(regionIdDTO.getBody());
            // 更新用户关联的云服务器状态
            userCloudServersRelationService.updateCloudServiceStatusByServerIds(regionIdDTO.getBody().getBody().getServers(), ServerStatusEnum.DELETED);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("deleteServers error:{}", e.getMessage());
        }
        return response;
    }

    @Override
    public CancelAutoRenewalResourcesResponse cancelAutoRenewalResources(CancelAutoRenewalResourcesRequest cancelAutoRenewalResourcesRequest) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        CancelAutoRenewalResourcesResponse response = null;
        try {
            response = client.cancelAutoRenewalResources(cancelAutoRenewalResourcesRequest);
            System.out.println(response.toString());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("cancelAutoRenewalResources error:{}", e.getMessage());
        }
        return response;
    }

    @Override
    public List<CnRegion> regionList() {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        List<CnRegion> cnRegionList = CnRegionServiceImpl.getCnRegionList();
        String regionId = accountSetting.getRegionId();
        // cnRegionList中 将regionId放在第一个
        if (StringUtils.isNotEmpty(regionId)) {
            CnRegion cnRegion = cnRegionList.stream().filter(f -> regionId.equals(f.getRegionId())).findFirst().orElse(null);
            if (cnRegion != null) {
                cnRegionList.remove(cnRegion);
                cnRegionList.add(0, cnRegion);
            }
        }
        return cnRegionList.stream().filter(f -> StringUtils.isNotEmpty(f.getRegionName())).collect(Collectors.toList());
    }



    /**
     * 生成创建云服务器请求参数
     *
     * @param rateOnPeriodReq 请求参数
     */
    private void genListOnDemandResourceRatingsRequest(RateOnPeriodReqDTO rateOnPeriodReq) {
        if (rateOnPeriodReq == null) {
            return;
        }
        List<PeriodProductInfo> productInfos = rateOnPeriodReq.getProductInfos();
        if (productInfos == null || productInfos.size() == 0) {
            return;
        }
        for (PeriodProductInfo productInfo : productInfos) {
            productInfo.setRegion(rateOnPeriodReq.getRegionId());

            switch (productInfo.getCloudServiceType()) {
                // 弹性云服务器
                case "hws.service.type.ec2":
                    productInfo.setId("ec2");
                    productInfo.setResourceType("hws.resource.type.vm");
                    break;
                // 硬盘
                case "hws.service.type.ebs":
//                    productInfo.setId("ebs");
                    productInfo.setResourceType("hws.resource.type.volume");
                    productInfo.setSizeMeasureId(17);
                    if (Objects.isNull(productInfo.getResourceSize())) {
                        throw new ServiceException("硬盘大小不能为空");
                    }
                    break;
                case "hws.service.type.vpc":
                    // 弹性公网IP
                    if (productInfo.getResourceType().equals("hws.resource.type.ip")) {
                        productInfo.setId("eip");
                        productInfo.setResourceSpec(rateOnPeriodReq.getEipType());
                        // 带宽
                    } else if (productInfo.getResourceType().equals("hws.resource.type.bandwidth")) {
                        productInfo.setId("bandwidth");
                        /*
                            12_bgp：动态BGP按流量计费带宽
                            12_sbgp：静态BGP按流量计费带宽
                            19_bgp：动态BGP按带宽计费带宽
                            19_sbgp：静态BGP按带宽计费带宽
                            19_share：按带宽计费共享带宽
                        */
//                        productInfo.setResourceSpec("19_bgp"); // 静态BGP按带宽计费带宽
                        if (Objects.isNull(productInfo.getResourceSpec())) {
                            throw new ServiceException("线路不能为空");
                        }
                        productInfo.setSizeMeasureId(15);
                        if (Objects.isNull(productInfo.getResourceSize())) {
                            throw new ServiceException("带宽大小不能为空");
                        }
                        if (productInfo.getResourceSize() < 1 || productInfo.getResourceSize() > 2000) {
                            throw new ServiceException("带宽大小范围为1-2000");
                        }
                    }
                    break;
            }
        }
    }
}
